package com.zjut.an.util.system;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringEscapeUtils;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class XssInterceptor extends AbstractInterceptor{

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        // TODO Auto-generated method stub
    	//System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
        ActionContext actionContext = invocation.getInvocationContext();
        Map<String, Object> map = actionContext.getParameters();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String value =  ((String[])(entry.getValue()))[0];
            //System.out.println("@@@@@@过滤前:"+value);
			/*
			 * value = value.replaceAll("<", "").replaceAll(">", ""); value =
			 * value.replaceAll("script", ""); value = value.replaceAll("=", ""); value =
			 * value.replaceAll("'", ""); value = value.replaceAll("(", ""); value =
			 * value.replaceAll(")", ""); value = value.replaceAll(" ", ""); value =
			 * value.replaceAll("(?i)onmouse", ""); value = value.replaceAll("(?i)on", "");
			 */
            value = cleanXSS(value);
            value = cleanXSS2(value);
            value = cleanXSS3(value);
            
            entry.setValue(value);//将提交上来的字符串进行转码
            //System.out.println("@@@@@@过滤后:"+(entry.getValue()));
        }
        return invocation.invoke();
    }
    
    /**
     * 转义字符,使用该方法存在一定的弊端
     * 
     * @param value
     * @return
     */
    private String cleanXSS3(String value) {
        // 移除特殊标签
    	String[] replaces = "alert|onclick|ondatabinding|ondblclick|ondisposed|oninit|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onprerender|onunload|onerror|onfocus|prompt".split("\\|");
    	//System.out.println(value);
    	for (int i=0; i<replaces.length; i++) {
    		//System.out.println("replace:"+replaces[i]);
    		value = value.replaceAll("(?i)"+replaces[i], "");
    	}
    	//System.out.println("移除特殊代码："+value);
        return value;
    }
    
    /**
     * 转义字符,使用该方法存在一定的弊端
     * 
     * @param value
     * @return
     */
    private String cleanXSS2(String value) {
        // 移除特殊标签
        value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
        value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
        value = value.replaceAll("'", "&#39;");
        value = value.replaceAll("`", "&#39;");
        value = value.replaceAll("/", "&#x2F;");        
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        value = value.replaceAll("(?i)"+"script", "");
        // System.out.println("移除特殊标签："+value);
        return value;
    }
    /**
    * 真正实现过滤关键词的操作
    **/
        private String cleanXSS(String value) {
            if (value != null) {
            	//value = ESAPI.encoder().canonicalize(value);
                //推荐使用ESAPI库来避免脚本攻击,value = ESAPI.encoder().canonicalize(value);
                // 避免空字符串
                //value = value.replaceAll(" ", "");
                // 避免script 标签
                Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // 避免src形式的表达式
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // 删除单个的 </script> 标签
                scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // 删除单个的<script ...> 标签
                scriptPattern = Pattern.compile("<script(.*?)>",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // 避免 eval(...) 形式表达式
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // 避免 e­xpression(...) 表达式
                scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // 避免 javascript: 表达式
                scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // 避免 vbscript:表达式
                scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // 避免 οnlοad= 表达式
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
            }

        	//System.out.println("移除关键词："+value);
            return value;
        }
}